/*
 * Copyright 2010-2012 VMware and contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

package cn.wenhao.javaClassReload.javaClassElements;

import java.util.List;

import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.FieldNode;

import cn.wenhao.javaClassReload.invoker.MethodInvoker;
import cn.wenhao.javaClassReload.utils.GenericsUtils;
import lombok.Data;

/**
 * 
 * @say little Boy, don't be sad.
 * @name Rezar
 * @time Oct 27, 2016
 * @Desc Describes a field, created during TypeDescriptor construction.
 */
@Data
public class FieldMember extends AbstractMember {

    public static final FieldMember[] NONE = null;

    String typename;

    private Object fieldValue;

    public FieldMember(String typename, int modifiers, String name, String descriptor, String signature) {
        super(modifiers, name, descriptor, signature);
        this.typename = typename;
    }

    public String getDeclaringTypeName() {
        return typename;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("0x").append(Integer.toHexString(modifiers));
        sb.append(" ").append(descriptor).append(" ").append(name);
        if (signature != null) {
            sb.append(" [").append(signature).append("]");
        }
        return sb.toString().trim();
    }

    @Override
    public boolean equals(Object other) {
        if (!(other instanceof FieldMember)) {
            return false;
        }
        FieldMember o = (FieldMember) other;
        if (!name.equals(o.name)) {
            return false;
        }
        if (modifiers != o.modifiers) {
            return false;
        }
        if (!descriptor.equals(o.descriptor)) {
            return false;
        }
        if (signature == null && o.signature != null) {
            return false;
        }
        if (signature != null && o.signature == null) {
            return false;
        }
        if (signature != null) {
            if (!signature.equals(o.signature)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        int result = modifiers;
        result = result * 37 + name.hashCode();
        result = result * 37 + descriptor.hashCode();
        if (signature != null) {
            result = result * 37 + signature.hashCode();
        }
        return result;
    }

    /**
     * @param fieldNode
     * @return
     */

    @SuppressWarnings("unchecked")
    public static FieldMember newInstance(FieldNode fieldNode) {

        String fieldDesc = fieldNode.desc;
        Type type = Type.getType(fieldDesc);
        int access = fieldNode.access;
        List<AnnotationNode> visibleAnnotations = fieldNode.visibleAnnotations;
        String name = fieldNode.name;
        String signature = fieldNode.signature;
        Object value = fieldNode.value;

        FieldMember fieldMember = new FieldMember(type.getClassName(), access, name, fieldDesc, signature);
        fieldMember.setFieldValue(value);

        /**
         * 未处理注解 TODO
         */
        if (GenericsUtils.notNullAndEmpty(visibleAnnotations)) {
            // for (AnnotationNode an : visibleAnnotations) {
            // String anDesc = an.desc;
            // List values = an.values;
            // }
        }
        return fieldMember;
    }

    /**
     * @return
     */
        
    public String getGenericSignature() {
        return signature;
    }

}
